package com.lyeducation.controllers; // package com.lyeducation.controllers;

import com.alibaba.fastjson.JSON;
import com.lyeducation.controllers.dto.ChatDto;
import com.lyeducation.entities.chat.OfflineMsgEntity;
import com.lyeducation.entities.system.SysUserEntity;
import com.lyeducation.repository.OfflineMsgRepository;
import com.lyeducation.repositoryImpl.OfflineMsgRepositoryImpl;
import com.lyeducation.util.JsonUtils;
import com.lyeducation.util.SpringUtil;
import io.swagger.annotations.Api;
import org.hibernate.transform.Transformers;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

@Api(
        value = "客服",
        tags = {"客户与客服聊天接口"},
        description = "客户与客服聊天接口"
)
@Component
@ServerEndpoint(value = "/chat/{userId}")
public class ChatController implements CustomerChatService {

    private StringRedisTemplate redisTampate = SpringUtil.getBean(StringRedisTemplate.class);

    PublishService publishService = SpringUtil.getBean(PublishService.class);

    private RedisMessageListenerContainer redisMessageListenerContainer =
            SpringUtil.getBean(RedisMessageListenerContainer.class);

    private OfflineMsgRepository offlineMsgRepository =
            SpringUtil.getBean(OfflineMsgRepositoryImpl.class);

    private String[] getAdminId() {
        String[] a = new String[1];
        a[0] = "1";
        return a;
    }

    //    public static HashMap<String, String> getUserAdmin() {
    //        return userAdmin;
    //    }

    //    private static volatile HashMap<String, String> userAdmin = new HashMap<>();

    private static volatile CopyOnWriteArraySet<String> notConnectionUserSessions =
            new CopyOnWriteArraySet<>();

    //    private static volatile HashMap<String, CopyOnWriteArraySet<String>> adminTpoics = new
    // HashMap();
    //
    //    private static volatile HashMap<String, Session> adminSessionMap = new HashMap();

    private static volatile HashMap<String, SubscribeListener> adminListener = new HashMap();
    private static volatile HashMap<String, SubscribeListener> userListener = new HashMap();
    private static volatile HashMap<String, String> userAdminTopic = new HashMap();
    private Session session;

    //    public static synchronized void addAdminTopic(String adminId, String topic) {
    //        CopyOnWriteArraySet topicSet = adminTpoics.get(adminId);
    //        if (topicSet == null || topicSet.size() == 0) {
    //            topicSet = new CopyOnWriteArraySet();
    //            adminTpoics.put(adminId, topicSet);
    //        }
    //        topicSet.add(topic);
    //    }
    //    public String userAgainChatConnection(String userId) {
    //        String adminId = null;
    //        Session adminSession = null;
    //        String topic = null;
    //        if (adminSessionMap.size() > 0) {
    //            session.getUserProperties().put("userName", "用户777");
    //            Set<String> set = adminSessionMap.keySet();
    //            ArrayList<String> arrayList = new ArrayList(set);
    //            adminId = arrayList.get(new Random().nextInt(set.size()));
    //            //                由用户建立连接
    //            topic = userId;
    //            //                userSessions.put(this, topic);
    //            adminSession = adminSessionMap.get(adminId);
    //            //            Session adminSession=null;
    //            adminTpoics.get(adminId).add(userId);
    //            userSessions.add(topic);
    //            if (topic != null) {
    //                SubscribeListener subscribeListener = new SubscribeListener();
    //                subscribeListener.setSession(session);
    //                subscribeListener.setStringRedisTemplate(redisTampate);
    //                redisMessageListenerContainer.addMessageListener(
    //                        subscribeListener, new ChannelTopic(topic));
    //                PublishService publishService = null;
    //                if (adminSession != null) {
    //                    publishService = SpringUtil.getBean(PublishService.class);
    //                    ChatDto chatDto = new ChatDto();
    //                    //        SecurityPrincipalContext.getUserDetailsImpl().getUsername()
    //                    chatDto.setFromId(userId);
    //                    chatDto.setCreateTime(new Date());
    //                    chatDto.setMsg("您好,客服" + adminSession.getUserProperties().get("userName") +
    // "为您服务");
    //                    publishService.publish(topic, JsonUtils.toJson(chatDto));
    //                    //
    // publishService.publish(adminSessions.get(adminSession),
    //                    // JsonUtils.toJson(chatDto));
    //                }
    //                SubscribeListener subscribeListener2 = new SubscribeListener();
    //                subscribeListener2.setSession(adminSession);
    //                subscribeListener2.setStringRedisTemplate(redisTampate);
    //                redisMessageListenerContainer.addMessageListener(
    //                        subscribeListener2, new ChannelTopic(topic));
    //            }
    //        }
    //        return topic;
    //    }

    private SubscribeListener createSubscribeListener(String userId) {
        SubscribeListener subscribeListener = new SubscribeListener();
        subscribeListener.setSession(session);
        subscribeListener.setStringRedisTemplate(redisTampate);
        return subscribeListener;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) throws IOException {
        this.session = session;
        //        if(SecurityPrincipalContext.checkHasAdminOrGeneralAdminRole()){
        //
        //        }
        //        SecurityPrincipalContext.getUserDetailsImpl().getId()
        if (!setAndSendBaseMsgById(userId)) {
            return;
        }

        String topic = null;
        String adminId = null;
        //    SecurityPrincipalContext.checkHasAdminOrGeneralAdminRole() ||
        // 不论客服客户建立通讯频道
        SubscribeListener subscribeListener = null;
        SubscribeListener oldSub = null;
        if ("1".equals(userId)) {
            //            获取管理员基础信息
            oldSub = adminListener.get(userId);
            if (oldSub != null) {
                oldSub.getSession().close();
                subscribeListener = oldSub;
                subscribeListener.setSession(session);
            }
            if (subscribeListener == null) subscribeListener = createSubscribeListener(userId);

            adminListener.put(userId, subscribeListener);
            if (notConnectionUserSessions.size() > 0) {
                //        解决已连接到服务器的客户但未连上客服

                String fromImg = session.getUserProperties().get("img").toString();
                String fromName = session.getUserProperties().get("name").toString();
                for (String user : notConnectionUserSessions) {
                    userAdminTopic.put(user, userId);
                    ChatDto chatDto = new ChatDto();
                    //        SecurityPrincipalContext.getUserDetailsImpl().getUsername()
                    chatDto.setFromId(userId);
                    chatDto.setFromImg(fromImg);
                    chatDto.setFromName(fromName);
                    chatDto.setCreateTime(new Date());
                    chatDto.setMsg("您好,客服" + fromName + "为您服务");
                    chatDto.setToId(user);
                    chatDto.setType(0);
                    try {
                        publishService.publish(user, JSON.toJSONString(chatDto));
                    } catch (Exception e) {
                        userListener.get(user).getSession().close();
                    }
                }
                notConnectionUserSessions.clear();
            }
            //      topic = SecurityPrincipalContext.getUserDetailsImpl().getId();
            //            topic = role;

            getOldMeg(userId, true);
            // 每一个建立自己的连接topic message时查看是否有1-1连接如果没有再重新随机建立一个
        } else {
            oldSub = userListener.get(userId);
            if (oldSub != null) {
                oldSub.getSession().close();
                subscribeListener = oldSub;
                subscribeListener.setSession(session);
            }
            if (subscribeListener == null) subscribeListener = createSubscribeListener(userId);
            userListener.put(userId, subscribeListener);
            topic = userId;
            getOldMeg(userId, false);
            if (adminListener.size() > 0) {
                Set<String> set = adminListener.keySet();
                ArrayList<String> arrayList = new ArrayList(set);
                adminId = arrayList.get(new Random().nextInt(set.size()));
                Session adminSession = adminListener.get(adminId).getSession();
                userAdminTopic.put(userId, adminId);
                ChatDto chatDto = new ChatDto();
                chatDto.setFromId(adminId);
                chatDto.setFromImg(adminSession.getUserProperties().get("img").toString());
                chatDto.setMsg("客服" + adminSession.getUserProperties().get("name").toString() + "为您服务");
                chatDto.setFromName(adminSession.getUserProperties().get("name").toString());
                try {
                    publishService.publish(userId, JSON.toJSONString(chatDto));
                } catch (Exception e) {
                    adminListener.get(userId).getSession().close();
                }
            } else {
                notConnectionUserSessions.add(userId);
                ChatDto chatDto = new ChatDto();
                chatDto.setFromId("1");
                chatDto.setMsg("客服未上线");
                chatDto.setFromName("客服7");
                session.getBasicRemote().sendText(JsonUtils.toJson(chatDto));
            }
        }
        redisMessageListenerContainer.addMessageListener(subscribeListener, new ChannelTopic(userId));
        //
        //        if (topic != null) {
        //            SubscribeListener subscribeListener = new SubscribeListener();
        //            subscribeListener.setSession(session);
        //            subscribeListener.setStringRedisTemplate(redisTampate);
        //            redisMessageListenerContainer.addMessageListener(subscribeListener, new
        // ChannelTopic(topic));
        //            PublishService publishService = null;
        //            getOldMeg(userId);
        //            if (adminSession != null) {
        //                publishService = SpringUtil.getBean(PublishService.class);
        //                ChatDto chatDto = new ChatDto();
        //                //        SecurityPrincipalContext.getUserDetailsImpl().getUsername()
        //                chatDto.setFromId("1");
        //                chatDto.setCreateTime(new Date());
        //                chatDto.setMsg("您好,客服" + adminSession.getUserProperties().get("userName") +
        // "为您服务");
        //                chatDto.setToId(userId);
        //                publishService.publish(topic, JsonUtils.toJson(chatDto));
        //                //                    publishService.publish(adminSessions.get(adminSession),
        //                // JsonUtils.toJson(chatDto));
        //                SubscribeListener subscribeListener2 = new SubscribeListener();
        //                subscribeListener2.setSession(adminSession);
        //                subscribeListener2.setStringRedisTemplate(redisTampate);
        //                redisMessageListenerContainer.addMessageListener(
        //                        subscribeListener2, new ChannelTopic(topic));
        //            } else {
        //                ChatDto chatDto = new ChatDto();
        //                chatDto.setFromId("1");
        //                chatDto.setMsg("客服未上线");
        //                chatDto.setFromName("客服7");
        //                session.getBasicRemote().sendText(JsonUtils.toJson(chatDto));
        //            }
        //        } else {
        //            if (!userId.equals("1")) {
        //                getOldMeg(userId);
        //                ChatDto chatDto = new ChatDto();
        //                chatDto.setFromId("1");
        //                chatDto.setMsg("客服未上线");
        //                chatDto.setFromName("客服7");
        //                session.getBasicRemote().sendText(JsonUtils.toJson(chatDto));
        //            }
        //        }
    }

    /**
     * @param session
     * @param message
     * @throws IOException
     */
    @OnMessage
    public void onMessage(Session session, String message) throws IOException {
        ChatDto chatDto = JSON.parseObject(message, ChatDto.class);
        //      SecurityPrincipalContext.getUserDetailsImpl().getUsername()
        String sessionUserId = session.getUserProperties().get("id").toString();
        String topic = null;

        //        if (userSessions.contains(sessionUserId) ) {
        //            List<Object[]> adminTopicSessionList = adminSessions.get(chatDto.getToId());
        //
        //            if (adminTopicSessionList != null && adminTopicSessionList.size() > 0) {
        //                for (Object[] objects : adminTopicSessionList) {
        //                    String checkTopic = null;
        //                    if (objects[0] != null) {
        //                        checkTopic = (String) objects[0];
        //                    }
        //                    if (sessionUserId.equals(checkTopic)) {
        //                        topic = checkTopic;
        //                    }
        //                }
        //            }
        //            if (topic == null) {
        //                topic = userAgainChatConnection(topic);
        //            }
        //
        //        } else if (sessionUserId.equals("2")) {
        //            if (topic == null) {
        //                topic = userAgainChatConnection(sessionUserId);
        //            }
        //        }
        //        List<Object[]> adminTopicSessionList = adminSessions.get(sessionUserId);
        //        if (adminTopicSessionList != null && adminTopicSessionList.size() > 0) {
        //            for (Object[] objects : adminTopicSessionList) {
        //                String checkTopic = null;
        //                if (objects[0] != null) {
        //                    checkTopic = (String) objects[0];
        //                }
        //                if (chatDto.getToId().equals(checkTopic)) {
        //                    topic = checkTopic;
        //                    break;
        //                }
        //                if (userSessions.contains(chatDto.getToId())) {
        //                    topic = checkTopic;
        //                    break;
        //                }
        //            }
        //        }
        if (sessionUserId.equals(chatDto.getToId())) {
            return;
        }
        if (userAdminTopic.keySet().contains(sessionUserId)) {
            if (userAdminTopic.values().contains(chatDto.getToId())) {
                topic = chatDto.getToId();
            }
        } else {
            if (userAdminTopic.values().contains(sessionUserId)) {
                if (userAdminTopic.keySet().contains(chatDto.getToId())) {
                    topic = chatDto.getToId();
                }
            }
        }

        if (topic != null) {
            chatDto.setFromId(sessionUserId);
            chatDto.setFromName(session.getUserProperties().get("name").toString());
            chatDto.setType(1);
            //            String topic = this.getSession().getUserProperties().get("topic").toString();
            //            if (topic == null) {
            //                //            topic = adminSessions.get(this);
            //            }
            try {
                publishService.publish(topic, JSON.toJSONString(chatDto));
            } catch (Exception e) {
                SubscribeListener subscribeListener = userListener.get(topic);
                if (subscribeListener == null) {
                    subscribeListener = adminListener.get(topic);
                }
                subscribeListener.getSession().close();
            }

        } else {
            OfflineMsgEntity offlineMsgEntity = new OfflineMsgEntity();
            offlineMsgEntity.setFromId(sessionUserId);
            offlineMsgEntity.setName(session.getUserProperties().get("userName").toString());
            offlineMsgEntity.setToId(chatDto.getToId());
            offlineMsgEntity.setMsg(chatDto.getMsg());
            offlineMsgRepository.save(offlineMsgEntity);
        }
    }

    @OnClose
    public void onClose(Session session) {
        Object id = session.getUserProperties().get("id");
        if (id != null) clearChat(id.toString());
        //    userSessions.remove(this);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        //        clearChat(session.getUserProperties().get("id").toString());
        System.out.println(error.getMessage());
    }

    private void clearChat(String id) {
        MessageListener messageListener = adminListener.remove(id);
        if (messageListener != null) {
            redisMessageListenerContainer.removeMessageListener(messageListener, new ChannelTopic(id));
            Iterator<Map.Entry<String, String>> it = userAdminTopic.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> userAdmin = it.next();
                if (id.equals(userAdmin.getValue())) {
                    notConnectionUserSessions.add(userAdmin.getKey());
                    it.remove();
                }
            }

        } else {
            messageListener = userListener.remove(id);
            if (messageListener != null) {
                redisMessageListenerContainer.removeMessageListener(messageListener, new ChannelTopic(id));
            }
            userAdminTopic.remove(id);
        }
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    private boolean setAndSendBaseMsgById(String id) throws IOException {
        ChatDto chatDto = new ChatDto();
        LinkedHashMap linkedHashMap = new LinkedHashMap<String, String>();
        linkedHashMap.put("id", id);
        String sql = "select u.name,u.photo from sys_user as u where u.isDelete=false and u.id=:id ";
        List<SysUserEntity> list =
                offlineMsgRepository.findByNativeQuery(
                        sql, linkedHashMap, Transformers.aliasToBean(SysUserEntity.class));

        if (list != null && list.size() == 1) {
            SysUserEntity offlineMsgEntity = list.get(0);
            chatDto.setFromName(offlineMsgEntity.getName());
            chatDto.setFromImg(offlineMsgEntity.getPhoto());
            chatDto.setType(0);
            session.getUserProperties().put("id", id);
            String img = offlineMsgEntity.getPhoto();
            String name = offlineMsgEntity.getName();
            if (img != null) session.getUserProperties().put("img", img);
            if (name != null) session.getUserProperties().put("name", name);
            session.getBasicRemote().sendText(JsonUtils.toJson(chatDto));
            return true;
        } else {
            session.close();
        }
        return false;
    }

    private boolean getOldMeg(String toId, boolean isAdmin) throws IOException {

        LinkedHashMap linkedHashMap = new LinkedHashMap<String, String>();
        linkedHashMap.put("toId", toId);
        String sql = "";
        if (isAdmin)
            sql =
                    "select * from offline_msg where isDelete=false and toId=:toId or toId=\"admin\" ORDER BY createTime asc";
        else
            sql = "select * from offline_msg where isDelete=false and toId=:toId ORDER BY createTime asc";
        List<OfflineMsgEntity> list = offlineMsgRepository.findByNativeQuery(sql, linkedHashMap);
        if (list != null && list.size() > 0) {
            for (OfflineMsgEntity offlineMsgEntity : list) {
                ChatDto chatDto = new ChatDto();
                chatDto.setFromName(offlineMsgEntity.getName());
                chatDto.setMsg(offlineMsgEntity.getMsg());
                chatDto.setFromId(offlineMsgEntity.getFromId());
                chatDto.setToId(offlineMsgEntity.getToId());
                chatDto.setCreateTime(offlineMsgEntity.getCreateTime());
                session.getBasicRemote().sendText(JsonUtils.toJson(chatDto));
            }
            if (isAdmin) sql = "set isDelete=true where toId=:toId or toId='admin' and isDelete=false";
            else sql = "set isDelete=true where toId=:toId and isDelete=false";
            offlineMsgRepository.updateFileds(sql, linkedHashMap, null);
            if (isAdmin) {
                sql = "set toId=:toId where toId='admin'";
                offlineMsgRepository.updateFileds(sql, null, linkedHashMap);
            }
            return true;
        }
        return false;
    }
}
